﻿#include <Sys\RenderUnit\SysRenderDatagram\LIGHTATTRIBRD.HPP>
#include <Render\Render_Win32\Render_Win32_OpenGL\RENDER_WIN32_OPENGL.HPP>
#include <Sys\RenderUnit\SYSDDCLASSID.HPP>

using namespace CxxlMan;
using namespace Cxxl3D;


class CLightAttribDD_OpenGL:public IDatagramDisposal_OpenGL, public ILightAttribBridge
{
  class CLightAttrib_CEO:public ILightAttrib_CEO
  { 
    bool m_Specular; // 是否有反射的功能
    C3D_FLOAT m_Color[4];


    // 燈光功能 true = ON  false = OFF 
    virtual void cxxlFASTCALL Light(bool Switch)
    {
      if(Switch)
        glEnable(GL_LIGHTING);
      else
        glDisable(GL_LIGHTING);
    }

    // 反光功能 true = ON  false = OFF 
    virtual void cxxlFASTCALL Specular(bool Switch)
    {
      m_Specular = Switch;
      if(m_Specular)
      {
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_Color);
      }
      else
      {
        C3D_FLOAT Dark[4] = {0,0,0,1};
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Dark);
      }      
    }

    // Switch = true:計算每個頂點到鏡頭的向量 false:假設頂點就在鏡頭前方，加快速度
    virtual void cxxlFASTCALL Specular_LocalViewer(bool Switch)
    {
      glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, Switch);
    }

    // 是否為 Normalize 做正規化處理
    // Switch = true:是  false:否
    /*
    virtual void cxxlFASTCALL AutoNormalize(bool Switch) 
    {
      if ( Switch )
        glEnable(GL_NORMALIZE);
      else
        glDisable(GL_NORMALIZE);
    }
    */


    // 設定顏色
    virtual void cxxlFASTCALL SetColor(C3D_FLOAT *Color)
    {
      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Color);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Color);

      m_Color[0] = Color[0];
      m_Color[1] = Color[1];
      m_Color[2] = Color[2];
      m_Color[3] = Color[3];

      if(m_Specular)
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_Color);
      else
      {
        C3D_FLOAT Dark[4] = {0,0,0,1};
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Dark);
      }      
    }

    // 設定 Emissive 顏色
    virtual void cxxlFASTCALL SetEmissive(C3D_FLOAT *EmissiveColor)
    {
      glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, EmissiveColor);
    }


    // 設定材質反光銳利度
    virtual void cxxlFASTCALL SetMaterialShininess(C3D_FLOAT MaterialShininess)
    {
      glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, MaterialShininess);
    }

  public:
    CLightAttrib_CEO()
    {
      m_Specular = false;
      m_Color[0] = m_Color[1] = m_Color[2] =  0;
      m_Color[3] = 1;
    }
    virtual ~CLightAttrib_CEO(){}

  }Attrib_CEO;


  virtual bool cxxlFASTCALL Exec(const Smart_Ptr<IRenderDatagramDisposalCenterOpengl> &IRenderDatagramDisposalCenter_Arg,
    const Smart_Ptr<IRenderDatagram> &IRenderDatagram_Arg, const CxxlMan::CSmart_Ptr<Matrix4x4> &ViewMatrix_Arg)
  {
    if(actILightAttribRD_Ptr.isNULL())
    {
      if(IRenderDatagram_Arg.isNULL() == false)
      {
        actILightAttribRD_Ptr = (ILightAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
        isModified(actILightAttribRD_Ptr);
        SetAll(actILightAttribRD_Ptr, &Attrib_CEO);
      }
    }
    else if(isModified(actILightAttribRD_Ptr))
    {
      if(IRenderDatagram_Arg.isNULL() == false)
        actILightAttribRD_Ptr = (ILightAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);

      SetAll(actILightAttribRD_Ptr, &Attrib_CEO);
    }
    else if(IRenderDatagram_Arg.isNULL() == false)
    {
      Smart_Ptr<ILightAttribRD> ILightAttribRD_Ptr = (ILightAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
      if((ILightAttribRD*)actILightAttribRD_Ptr != (ILightAttribRD*)ILightAttribRD_Ptr)
      {
        Chk(actILightAttribRD_Ptr, ILightAttribRD_Ptr, &Attrib_CEO);
        actILightAttribRD_Ptr = ILightAttribRD_Ptr;
      }
    }

    return true;
  }

  Smart_Ptr<ILightAttribRD> actILightAttribRD_Ptr;

public:
  // Consteructor
  CLightAttribDD_OpenGL()
    :cxxlObject(Spirit_Easy),
    actILightAttribRD_Ptr(NULL,this)
  {
  }

  // Desteructor
  virtual ~CLightAttribDD_OpenGL()
  {
  }

};

cxxlObject *cxxlFASTCALL New_CLightAttribDD_OpenGL()
{
  return new CLightAttribDD_OpenGL;
}